Why in JavaScript both "Object instanceof Function" and "Function instanceof Object" return true?

一、ECMA5.1规范中instanceof

/*
how instanceof is defined by ECMA 5.1 Specification:

The production RelationalExpression: RelationalExpression instanceof ShiftExpression is evaluated as follows:

Let lref be the result of evaluating RelationalExpression.
    Let lval be GetValue(lref).
    Let rref be the result of evaluating ShiftExpression.
    Let rval be GetValue(rref).
    If Type(rval) is not Object, throw a TypeError exception.
    If rval does not have a [[HasInstance]] internal method, throw a TypeError exception.
    Return the result of calling the [[HasInstance]] internal method of rval with argument lval.

------->Not all objects will have [[HasInstance]] internal method, but functions.
        console.log(Object instanceof {});
        TypeError: Expecting a function in instanceof check, but got <Object>
    */

二、ECMA5.1规范中[[HasInstance]]

/*
how [[HasInstance]] has been defined in the ECMA 5.1 specification:
    Assume F is a Function object.
    When the [[HasInstance]] internal method of F is called with value V, the following steps are taken:

        If V is not an object, return false.
        Let O be the result of calling the [[Get]] internal method of F with property name "prototype".
        If Type(O) is not Object, throw a TypeError exception.
    Repeat
        Let V be the value of the [[Prototype]] internal property of V.
        If V is null, return false.
        If O and V refer to the same object, return true.
 ------->Take the prototype property of F and compare it
            with the [[Prototype]] internal property of O until it becomes null or prototype of F is the same as O.
        */

三、ECMA5.1规范中[[prototype]]

/*
what is the [[prototype]] internal property:
    All objects have an internal property called [[Prototype]].
    The value of this property is either null or an object and is used for implementing inheritance.
    Whether or not a native object can have a host object as its [[Prototype]] depends on the implementation.
    Every [[Prototype]] chain must have finite length(that is, starting from any object,
    recursively accessing the [[Prototype]] internal property must eventually lead to a null value).

------->We can get this internal property with the Object.getPrototypeOf function
*/
/*
[[HasInstance]] also talks about another property called prototype, which is specific to the Function objects.
    The value of the prototype property is used to
    initialise the [[Prototype]] internal property of a newly created object
    before the Function object is invoked as a constructor for that newly created object.

------->when a function object is used as a constructor, a new object will be created
        and the new object will have its internal [[Prototype]] initialized with this prototype property
------->function Test() {}
        Test.prototype.print = console.log;
        console.log(Object.getPrototypeOf(new Test()) === Test.prototype);
        # true
*/
console.log("-------------------------------------------------------" + "\n\n");

四、分析过程

//分析:

console.log(Object instanceof Function);
// true

// It will fetch Function.prototype first and it will try
// and find if that object is in the prototype hierarchy of Object. Let us see how that turns out
console.log(Function.prototype);
// [Function: Empty]
console.log(Object.getPrototypeOf(Object));
// [Function: Empty]
console.log(Object.getPrototypeOf(Object) === Function.prototype);
// true

//Since the Function.prototype matches the Object's internal property [[Prototype]], it returns true
console.log(Function instanceof Object);
// true
console.log(Object.prototype);
// {}
console.log(Object.getPrototypeOf(Function));
// [Function: Empty]
console.log(Object.getPrototypeOf(Function) === Object.prototype);
// false
console.log(Object.getPrototypeOf(Object.getPrototypeOf(Function)));
// {}
Object.getPrototypeOf(Object.getPrototypeOf(Function)) === Object.prototype
// true

//Here, first we get the Object.prototype, which is {}.
// Now it is trying to find if the same object {} is there in the Function's prototype chain.
// Immediate parent of Function is and Empty function.
console.log(Object.getPrototypeOf(Function));
// [Function: Empty]

//It is not the same as Object.prototype
console.log(Object.getPrototypeOf(Function) === Object.prototype);
// false

//But the [[HasInstance]] algorithm doesn't stop there. It repeats and gets up one more level
console.log(Object.getPrototypeOf(Object.getPrototypeOf(Function)));
// {}

//And this is the same as Object.prototype. That is why this returns true.
console.log("-------------------------------------------------------" + "\n\n");

五、证明流程

console.log(Object instanceof Function); // true
console.log(Function instanceof Object); // true
console.log(Object.prototype);
// {}
console.log(Object.getPrototypeOf(Function));
// [Function: Empty]
console.log(Object.getPrototypeOf(Function) === Object.prototype);
// false
console.log(Object.getPrototypeOf(Object.getPrototypeOf(Function)));
//{}
console.log(Object.getPrototypeOf(Object.getPrototypeOf(Function)) === Object.prototype);
// true
console.log(Object.getPrototypeOf(Function));
//[Function: Empty]
console.log(Object.getPrototypeOf(Function) === Object.prototype);
// false
console.log(Object.getPrototypeOf(Object.getPrototypeOf(Function)));
// {}
console.log("-------------------------------------------------------" + "\n\n");

陈杨
12 声望3 粉丝

不闻不若闻之,闻之不若见之,见之不若知之,知之不若行之,学至于行而止矣;行之,明也!